from typing import TypeVar, Generic, List, Optional
from pydantic import BaseModel, Field
from math import ceil

T = TypeVar('T')


class PaginationParams(BaseModel):
    """分页参数模型"""
    page: int = Field(1, ge=1, description="页码，从1开始")
    size: int = Field(10, ge=1, le=100, description="每页数量，最大100")
    
    @property
    def offset(self) -> int:
        """计算偏移量"""
        return (self.page - 1) * self.size
    
    @property
    def limit(self) -> int:
        """获取限制数量"""
        return self.size


class PaginationResponse(BaseModel, Generic[T]):
    """分页响应模型"""
    items: List[T] = Field(description="数据列表")
    total: int = Field(description="总数量")
    page: int = Field(description="当前页码")
    size: int = Field(description="每页数量")
    pages: int = Field(description="总页数")
    has_next: bool = Field(description="是否有下一页")
    has_prev: bool = Field(description="是否有上一页")
    
    @classmethod
    def create(cls, items: List[T], total: int, page: int, size: int) -> "PaginationResponse[T]":
        """创建分页响应"""
        pages = ceil(total / size) if total > 0 else 0
        return cls(
            items=items,
            total=total,
            page=page,
            size=size,
            pages=pages,
            has_next=page < pages,
            has_prev=page > 1
        )


class PaginationHelper:
    """分页工具类"""
    
    @staticmethod
    def validate_pagination_params(page: int, size: int, max_size: int = 100) -> tuple[int, int]:
        """
        验证分页参数
        
        Args:
            page: 页码
            size: 每页数量
            max_size: 最大每页数量
            
        Returns:
            tuple: (page, size) 验证后的参数
        """
        if page < 1:
            page = 1
        if size < 1:
            size = 10
        if size > max_size:
            size = max_size
        return page, size
    
    @staticmethod
    def get_offset(page: int, size: int) -> int:
        """计算偏移量"""
        return (page - 1) * size
    
    @staticmethod
    def get_total_pages(total: int, size: int) -> int:
        """计算总页数"""
        return ceil(total / size) if total > 0 else 0
    
    @staticmethod
    def has_next_page(page: int, total_pages: int) -> bool:
        """是否有下一页"""
        return page < total_pages
    
    @staticmethod
    def has_prev_page(page: int) -> bool:
        """是否有上一页"""
        return page > 1
    
    @staticmethod
    def get_page_info(page: int, size: int, total: int) -> dict:
        """获取分页信息"""
        total_pages = PaginationHelper.get_total_pages(total, size)
        return {
            "page": page,
            "size": size,
            "total": total,
            "pages": total_pages,
            "has_next": PaginationHelper.has_next_page(page, total_pages),
            "has_prev": PaginationHelper.has_prev_page(page),
            "offset": PaginationHelper.get_offset(page, size)
        }
